package excel

import (
	"encoding/json"
	"fmt"
	"github.com/pkg/errors"
	"github.com/xuri/excelize/v2"
)

func readTaskListFile(filePath string) (userTasks []*UserTask, err error) {
	f, err := excelize.OpenFile(filePath)
	if err != nil {
		println(err.Error())
		return
	}
	// 获取工作表中指定单元格的值
	//cell, err := f.GetCellValue("Sheet1", "B2")
	//if err != nil {
	//	println(err.Error())
	//	return
	//}
	//println(cell)
	// 获取 Sheet1 上所有单元格
	rows, err := f.GetRows("Sheet1")
	if err != nil {
		return
	}
	for i := 1; i < len(rows); i++ {
		var curUserTask = new(UserTask)
		curUserTask.Id = rows[i][0]
		curUserTask.TaskProcessConfigId = rows[i][1]
		curUserTask.PlayId = rows[i][2]
		curUserTask.Locale = rows[i][3]
		curUserTask.Uid = rows[i][4]
		curUserTask.TaskDag = new(TaskDag)
		if err = json.Unmarshal([]byte(rows[i][5]), curUserTask.TaskDag); err != nil {
			return
		}
		curUserTask.CreateTime = rows[i][6]
		curUserTask.DatachangeLasttime = rows[i][7]
		userTasks = append(userTasks, curUserTask)
	}
	return
}

var SheetName = "Sheet1"

func WriteUidToFile(userTasks []*UserTask, taskReq *TaskReq, fileName string) error {
	if len(userTasks) <= 0 {
		return errors.New("userTasks is null")
	}
	f := excelize.NewFile()
	// 创建一个工作表
	index := f.NewSheet(SheetName)
	// 设置表头
	initTitle(f)
	// 单元格行号
	var idx = 2
	var curReqItems = taskReq.TaskItem
	// 遍历每一个参与者
	for i := 0; i < len(userTasks); i++ {
		var curTasks = userTasks[i].TaskDag.NodeList
		if len(curTasks) < len(curReqItems) {
			continue
		}
		var hitAllTask = true
		// 遍历每一个筛选条件
		for j := 0; j < len(curReqItems); j++ {
			curReq := curReqItems[j]
			// 遍历一个参与者的所有任务
			var isFindTask = findTask(curReq, curTasks)
			if !isFindTask {
				hitAllTask = false
				break
			}

		}

		if hitAllTask {
			setLineValue(f, idx, userTasks[i])
			idx++
		}

	}
	// 设置工作簿的默认工作表
	f.SetActiveSheet(index)
	// 根据指定路径保存文件
	if err := f.SaveAs(fileName); err != nil {
		return err
	}
	return nil
}

func initTitle(f *excelize.File) {
	f.SetCellValue(SheetName, "A1", "id")
	f.SetCellValue(SheetName, "B1", "task_process_config_id")
	f.SetCellValue(SheetName, "C1", "play_id")
	f.SetCellValue(SheetName, "D1", "locale")
	f.SetCellValue(SheetName, "E1", "uid")
	f.SetCellValue(SheetName, "F1", "task_dag")
	f.SetCellValue(SheetName, "G1", "create_time")
	f.SetCellValue(SheetName, "H1", "datachange_lasttime")
}

func setLineValue(f *excelize.File, idx int, task *UserTask) error {
	f.SetCellValue(SheetName, fmt.Sprintf("%s%d", "A", idx), task.Id)
	f.SetCellValue(SheetName, fmt.Sprintf("%s%d", "B", idx), task.TaskProcessConfigId)
	f.SetCellValue(SheetName, fmt.Sprintf("%s%d", "C", idx), task.PlayId)
	f.SetCellValue(SheetName, fmt.Sprintf("%s%d", "D", idx), task.Locale)
	f.SetCellValue(SheetName, fmt.Sprintf("%s%d", "E", idx), task.Uid)
	taskTag, err := json.Marshal(task.TaskDag)
	if err != nil {
		return err
	}
	f.SetCellValue(SheetName, fmt.Sprintf("%s%d", "F", idx), string(taskTag))
	f.SetCellValue(SheetName, fmt.Sprintf("%s%d", "G", idx), task.CreateTime)
	f.SetCellValue(SheetName, fmt.Sprintf("%s%d", "H", idx), task.DatachangeLasttime)
	return nil
}

func findTask(curReq *TaskItem, curTasks []*Node) bool {
	for i := 0; i < len(curTasks); i++ {
		var curTask = curTasks[i]
		var sameTaskType = curReq.TaskType == curTask.TaskNodeConfig.TaskType
		var findStatus = len(curReq.TaskStatus) == 0
		for m := 0; m < len(curReq.TaskStatus); m++ {
			if curReq.TaskStatus[m] == curTask.TaskNodeConfig.TaskStatus {
				findStatus = true
			}
		}
		var findFinishTime = len(curReq.FinishedTimes) == 0
		for m := 0; m < len(curReq.FinishedTimes); m++ {
			if curReq.FinishedTimes[m] == curTask.TaskNodeConfig.FinishedTimes {
				findFinishTime = true
			}
		}
		if sameTaskType && findStatus && findFinishTime {
			return true
		}
	}
	return false
}

type TaskReq struct {
	TaskItem []*TaskItem
}

type TaskItem struct {
	TaskType      int
	TaskStatus    []int
	FinishedTimes []int
}

type UserTask struct {
	Id                  string   `json:"id"`
	TaskProcessConfigId string   `json:"task_process_config_id"`
	PlayId              string   `json:"play_id"`
	Locale              string   `json:"locale"`
	Uid                 string   `json:"uid"`
	TaskDag             *TaskDag `json:"task_dag"`
	CreateTime          string   `json:"create_time"`
	DatachangeLasttime  string   `json:"datachange_lasttime"`
}

type TaskDag struct {
	NodeList []*Node `json:"nodeList"`
}

type Node struct {
	TaskId         int             `json:"taskId"`
	TaskNodeConfig *TaskNodeConfig `json:"taskNodeConfig"`
}

type TaskNodeConfig struct {
	TaskId                int                    `json:"taskId"`
	TaskType              int                    `json:"taskType"`
	TaskStatus            int                    `json:"taskStatus"`
	QuotaId               int                    `json:"quotaId"`
	FinishedTimes         int                    `json:"finishedTimes"`
	NeedRepeatTimes       int                    `json:"needRepeatTimes"`
	QuotaGrantRule        *QuotaGrantRule        `json:"quotaGrantRule"`
	TaskSuccessDefinition *TaskSuccessDefinition `json:"taskSuccessDefinition"`
}

type QuotaGrantRule struct {
	RuleType     string `json:"ruleType"`
	FixPointRule *struct {
		Point int `json:"point"`
	} `json:"fixPointRule"`
	DiyRule *struct {
		Points []int `json:"points"`
	} `json:"diyRule"`
}

type TaskSuccessDefinition struct {
	Definitions []*struct {
		Id    int    `json:"id"`
		Value string `json:"value"`
	} `json:"definitions"`
}
